package cn.toolck.minitomcat.passer;

import cn.toolck.minitomcat.classLoader.MyClassLoader;
import cn.toolck.minitomcat.container.*;
import cn.toolck.minitomcat.map.Mapper;
import cn.toolck.minitomcat.service.Connector;
import cn.toolck.minitomcat.service.Service;
import cn.toolck.minitomcat.servlet.HttpServlet;
import org.dom4j.Element;

import java.io.File;
import java.io.FileFilter;
import java.util.List;
import java.util.Map;

/**
 * @ClassName ServerXmlPasser
 * @Description 进行ServerXml解析封装为Server对象
 * @Author Toolck Rin
 * @Date 2021/3/18 0:41
 * @Version 1.0
 **/
public class ServerXmlPasser extends Passer {

    public ServerXmlPasser(String fileName) {
        super(fileName);
    }

    public Server passFile() {
        Server server = new Server();
        Element rootElement = getDocument().getRootElement();
        List<Element> serviceEle = rootElement.selectNodes("//Service");
        for (int i = 0; i < serviceEle.size(); i++) {
            Element element = serviceEle.get(i);
            String serviceName = element.attributeValue("name");
            Service service = new Service();
            service.setName(serviceName);
            server.getServices().add(service);
            List<Element> connectorEles = element.selectNodes("//Connector");
            for (int j = 0; j < connectorEles.size(); j++) {
                Element connectorEle = connectorEles.get(i);
                String port = connectorEle.attributeValue("port");
                Connector connector = new Connector(Integer.valueOf(port));
                connector.setService(service);
                service.getConnectors().add(connector);
            }
            Element engineELe = (Element) element.selectSingleNode("//Engine");
            String engineName = engineELe.attributeValue("name");
            Engine engine = new Engine();
            engine.setName(engineName);
            service.setEngine(engine);
            Mapper mapper = engine.getMapper();
            List<Element> hostEles = engineELe.selectNodes("//Host");
            for (int j = 0; j < hostEles.size(); j++) {
                Element hostEle = hostEles.get(j);
                String hostName = hostEle.attributeValue("name");
                String appBase = hostEle.attributeValue("appBase");
                if (appBase.startsWith("/")) {
                    String tomcat = Thread.currentThread().getContextClassLoader().getResource("").getPath();
                    tomcat = tomcat.split("mini_tomcat")[0];
                    appBase = tomcat + "mini_tomcat" + appBase;
                }
                Host host = new Host();
                host.setName(hostName);
                host.setAppBase(appBase);
                host.setParent(engine);
                Mapper.MapperHost mapperHost = new Mapper.MapperHost();
                mapperHost.setName(hostName);
                mapperHost.setObj(host);
                mapper.getMapperHosts().add(mapperHost);
                List<Element> contextEles = hostEle.selectNodes("//Context");
                if (contextEles.size() == 0) {
                    canser(appBase, mapperHost);
                } else {
                    for (int k = 0; k < contextEles.size(); k++) {
                        Element contextEle = contextEles.get(k);
                        String contextName = contextEle.attributeValue("path");
                        String docBase = contextEle.attributeValue("docBase");
                        loadContext(mapperHost, contextName, docBase);
                    }
                }
            }

        }
        return server;
    }

    private void loadContext(Mapper.MapperHost mapperHost, String contextName, String docBase) {
        String path = mapperHost.getObj().getAppBase() + docBase;
        Mapper.MappedContext mappedContext = new Mapper.MappedContext();
        Context context = new Context();
        context.setDocBase(docBase);
        context.creatMyClassLoader(path + "/WEB-INF/classes");
        context.setName(contextName);
        context.setParent(mapperHost.getObj());
        mappedContext.setName(contextName);
        mappedContext.setObj(context);
        mapperHost.contexts.add(mappedContext);
        loadWarper(mappedContext, context, path);
    }

    private void loadWarper(Mapper.MappedContext mappedContext, Context context, String path) {
        MyClassLoader myClassLoader = context.getMyClassLoader();
        WebXmlPasser webXmlPasser = new WebXmlPasser(path + "/WEB-INF/web.xml", myClassLoader);
        Map<String, HttpServlet> stringHttpServletMap = webXmlPasser.passFile();
        stringHttpServletMap.forEach((key, servlet) -> {
            Wapper wapper = new Wapper();
            wapper.setServlet(servlet);
            wapper.setName(key);
            wapper.setParent(context);
            Mapper.MappedWapper mappedWapper = new Mapper.MappedWapper();
            mappedWapper.setName(key);
            mappedWapper.setObj(wapper);
            mappedContext.wappers.add(mappedWapper);
        });
    }

    private void canser(String appBase, Mapper.MapperHost mapperHost) {
        File file = new File(appBase);
        if (file.isDirectory()) {
            File[] files = file.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.isDirectory();
                }
            });
            for (int i = 0; i < files.length; i++) {
                File subFile = files[i];
                if (subFile.isDirectory()) {
                    String path = subFile.getPath();
                    String contextName = subFile.getName();
                    String docBase = "/" + contextName;
                    loadContext(mapperHost, contextName, docBase);
                }
            }
        }
    }
}
